tbillington / kondo Goto Github PK
View Code? Open in Web Editor NEWCleans dependencies and build artifacts from your projects.
License: MIT License
Cleans dependencies and build artifacts from your projects.
License: MIT License
Since Angular 13 the compiler adds a compilation cache folder called .angular/cache
by default, it would be useful to add it to the folders to be cleaned
It appears that kondo (as of commit 69c153b) detects Python projects by looking for a file with a .py
extension, at which point the directory in which this file is located is taken as the project root. However, this easily results in false negatives for modern Python packages, in which directories that need cleaning can be located above the directory of .py
files.
Note the following about Python projects:
setup.py
file (historical and now somewhat discouraged, but there's a lot of history), setup.cfg
(declarative form of setup.py
that was recommended for a while), and/or pyproject.toml
file (new standard) in the project root.setup.py
/setup.cfg
/pyproject.toml
. If all are absent, the most reliable marker for a project root is probably a requirements.txt
file, but this is purely conventional.
tox.ini
or noxfile.py
..py
files tend to be organized under a directory with the same or similar name to that of the project. This directory is either located in the project root or nested inside a src/
directory in the project root (though, in the latter case, I'd expect such projects to also be the kind to have a setup.py
, setup.cfg
, or pyproject.toml
file)..py
files to be located inside one or more levels of otherwise-empty non-src/
directories, though I think it'd be highly unusual to do this if you weren't planning on distributing the project.I tried kondo
in my home directory, and it ended up scanning everything due to a symlink:
'Steam/steamapps/common/Proton 7.0/dist/share/default_pfx/dosdevices/z:' -> /
It was taking a really long time, so I ran strace
and found that it was lost somewhere in .../z:/proc
. I know there are symlink loops in procfs
, and I think walkdir
is supposed to detect loops, so maybe it would have figured that out eventually. Still, I don't think it's a good default to follow links, and other tools I know like fd-find
and dua-cli
do not.
Semi-related, you might also want an option for same_file_system
, but that's less clear as a default.
kondo should inspect Makefile
s and run their respective clean command (make clean
)
When cwd is the root of my home directory (~
) and I run kondo
or kondo .
, it just displays Total bytes deleted: 0.0B
and does not even start searching through any directories it looks like.
kondo 0.4.0
edit: same with kondo @ 71d7539
I would like to run kondo in all directories below a directory (say dir
). Is there something like kondo -r dir
?
I am getting time information like "72 years ago", which is both unlikely and most importantly, not actually true. :)
For example, for a node_modules
directory with the date Jan 19 2018
I'm getting "72 years ago". I can't explain it through a confusion with months; that's more like 67 months ago.
For items months ago, I am getting plausible time periods.
I'm on Fedora 38. I installed the tool through cargo install
after cloning from git.
could you at least link similar projects?
Some languages & projects have system level caches/build artifacts.
For example the package cache for Unity, or the cargo cache for Rust.
Some kind of --system
parameter could be added to instruct kondo to check known system level caches instead of the usual directory based mode.
Hey there,
I went to check out the UI on linux (Pop_os 22.04, installed via cargo) but unfortunately, the icons in the main UI did not show up (strangely, the one in the title bar did, though).
Is a specific font required on the system for them to be displayed? I didn't see any mention of it, or any other font related issue posts, so I am not sure what is going on.
I just noticed that this particular icon did end up showing up once the search completed, but thats all?
... because many sections in the code are conditioned on target_os = "linux"
.
Conditions should include target_os = "freebsd"
.
Hi, thanks for this project!
It has been really useful for me, by showing me exactly how large those Rust target folders become :)
One nitpick: When I ran kondo
on my home directory, it took a very long time. That's ok, you're working on parallelization ๐. However, I'd have appreciated some kind of output to show me the process hasn't crashed :) Maybe add a --verbose
flag and output the name folder that's currently being analyzed?
Compiling kondo-ui
fails with the following error messages:
error[E0061]: this function takes 2 arguments but 1 argument was supplied
--> src/main.rs:187:21
|
187 | scan(&p).filter_map(|p| p.ok()).for_each(|project| {
| ^^^^---- an argument of type `&ScanOptions` is missing
|
note: function defined here
--> /tmp/kondo/kondo-lib/src/lib.rs:349:8
|
349 | pub fn scan<P: AsRef<path::Path>>(
| ^^^^
help: provide the argument
|
187 | scan(&p, /* &ScanOptions */).filter_map(|p| p.ok()).for_each(|project| {
| ~~~~~~~~~~~~~~~~~~~~~~~~
error[E0061]: this function takes 1 argument but 0 arguments were supplied
--> src/main.rs:189:52
|
189 | let project_size = project.size_dirs();
| ^^^^^^^^^-- an argument of type `&ScanOptions` is missing
|
note: associated function defined here
--> /tmp/kondo/kondo-lib/src/lib.rs:146:12
|
146 | pub fn size_dirs(&self, options: &ScanOptions) -> ProjectSize {
| ^^^^^^^^^
help: provide the argument
|
189 | let project_size = project.size_dirs(/* &ScanOptions */);
| ~~~~~~~~~~~~~~~~~~~~
For more information about this error, try `rustc --explain E0061`.
error: could not compile `kondo-ui` due to 2 previous errors
It looks like the GUI has a list of all the projects Kondo detected. Would it be possible to bring something like this to the CLI?
Npkill's TUI has a pretty cool way of doing this for reference (first GIF at https://github.com/voidcosmos/npkill shows it), though that exact interface would need something like ratatui which would be more complex than necessary.
(if you do replicate the npkill interface, please consider using space to stage changes then something like D
and confirm with y
to delete all staged deletions. Hitting space to instantly make a folder go poof is easy to mess up).
Awesome project with a great name, thank you for creating it!
Curious how useful being able to trash the artifacts instead of delete them would be, eg using https://github.com/Byron/trash-rs.
Integration looks like it wouldn't be too difficult. It seems to support the same platforms at kondo currently does.
kondo $(ls --ignore=.local/share/Steam --ignore=steamapps)
Error: Os { code: 2, kind: NotFound, message: "No such file or directory" }
The current project discovery logic of kondo fails in edge cases related to assumptions made during the initial implementation.
While the assumptions work for the vast majority of users it would be nice to not be bound by them. By removing them from the code the project will support more users and scenarios.
Users with a "root" directory that is being identified as a project, eg #29.
Projects with "sub-modules", eg #55 or tauri projects.
Directories that are more than a single project, eg a Cargo project that is also a Node project containing both Cargo.toml
and package.json
.
"Auxiliary projects" such as direnv raised in #101 that would almost always accompany a "regular" project in a directory, and may be too noisy to surface regularly.
Various Python project configurations, see #105 & #108.
Unity projects will have nested Node projects that should be ignored.
Rust workspace projects should ignore sub-crates that are in the workspace, but not ignore subdirectories that are not in the workspace.
Decide on if/how to handle git ignore.
Work is being done in https://github.com/tbillington/kondo/tree/discovery-rework.
For example, the target
dir at <rust_project>/examples/<example>/target
is ignored, only <rust_project>/target
is removed.
And if all examples were built for test purposes, the sum of those targets can often exceed the crate's main target
Hi, this is a question more than an issue. Sorry if this is not the right place for this.
I was wondering if there is an option to run kondo in non-interactive and maybe quiet mode? Something like kondo -a ~/code
to remove all artifacts in one command without manual input.
Thanks for all the work put into this helpful tool!
Kondo is successfully detecting my cargo projects. And it is successfully deleting some of them. However, some of them are erroring out with error removing directory "/path/to/directory": Os { code: 66, kind: DirectoryNotEmpty, message: "Directory not empty" }
. The directory is always the top-level target directory. And it seems that kondo is trying to delete this directory before it is deleted the entire contents.
For context, some of these directories are very large (the largest being ~170GB). Not sure if that could be part of the cause.
Hi.
I want to ignore some directories because I tend to run kondo $HOME
.
~ took 20s
โฏ kondo $(\ls --ignore=opt/nodebin)
/var/home/azzamsa/opt/nodebin Node project (5 minutes ago)
โโ node_modules (177.8MiB)
delete above artifact directories? ([y]es, [n]o, [a]ll, [q]uit): ^C
โฏ kondo $(exa --ignore-glob ~/opt/nodebin)
/var/home/azzamsa/opt/nodebin Node project (6 minutes ago)
โโ node_modules (177.8MiB)
delete above artifact directories? ([y]es, [n]o, [a]ll, [q]uit): n
Projects cleaned: 0, Bytes deleted: 0.0B
Nothing works.
Any suggestions?
Thanks! โค๏ธ
Some 3rd party project management tools include commands, or users add them by convention, that clean their workspace.
Eg Cargo
will remove target
, and users of Makefile
s and other scripting tools may create their own "clean" command.
Should kondo
defer to these tools?
I'm inclined to say yes, however there may be situations where kondo
knows more about the artifacts than the specific tool. There also may be situations where the user has implemented a clean command that performs some specific actions that kondo
can't reasonably mimic.
It's not obvious to me which path kondo
should take. I am erring on the side of not depending on the 3rd party tools because:
That being said, it does make sense to defer to tools like Cargo
s clean
command, since it is the standard for projects of that nature.
I have a project where I use python to script some misc tasks like testing. It seems that once a .py
file is detected it'll stop searching any other subdirectories since it marks the project as Python. This might have to get filed under the discovery rework since it might need project types to be non-exclusive which could take some extra refactoring.
Example: since the project root has a run.py
file, the cargo
and nodejs
projects aren't detected
project/
โโโ api/
โ โโโ src/
โ โโโ target/
โ โโโ tests/
โ โโโ Cargo.toml
โ โโโ test.py
โโโ web/
โ โโโ node_modules/
โ โโโ src/
โ โโโ package.json
โโโ run.py
Currently the code that walks directories will traverse into child directories even if the current directory is identified as one of the known project types. This is unnecessary for the default case, and is pure overhead.
It also means we need to perform the CPU intensive step of removing everything found inside that projects artifacts, eg the node_modules
of packages inside the top level node_modules
of a node project.
Downloaded latest binary, double click on .exe -> nothing happens
Hi.
When I use kondo
in my directory project, it deletes all the build artifacts in all directories. Including the active one.
woubuc/sweep: Reduce the disk usage of your projects by removing dependencies & builds on the other hand, only delete inactive directory: old projects that haven't been changed in more than a month.
Sweep (swp) finds old projects that haven't been changed in more than a month.
I thought I was missing some options. But I don't find any clue with kondo --help
.
Virtual environments are often named .venv
. For example, this is the name used by Poetry when creating the venv inside the project folder. They are also often named venv
, though maybe sometimes such a directory could contain things the user wants to keep (never met this, but who knows). I guess the leading dot of .venv
makes it safer to assume this is a virtualenv and that it can be removed.
Links:
Additionally, PEP582, which is used by some projects managers like PDM, says Python packages can be installed in a __pypackages__
directory.
Details here from Apple's crash reporter tool: https://gist.github.com/atroche/12272ee32ac71ff20fed9bcf2226ab46
It wasn't in response to anything I did in the UI btw -- it seemed to happen while I was in another window.
Thanks for making this :) You freed up a bunch of space on my machine.
OS: Linux Kubuntu 18.04
Kernel: 4.15.0-128-generic
AppVersion: 0.1.0 (the last from Cargo)
Terminal output (verbose):
popov@popov ~> env RUST_BACKTRACE=1 RUST_BACKTRACE=full /home/popov/.cargo/bin/kondo-ui
DEBUG [druid::localization] available locales [], current en-US
DEBUG [druid::localization] resolved: [en-US]
WARN [druid::menu] MenuDesc::platform_default is not implemented for this platform.
INFO [druid_shell::platform::gtk::application] gtk: Activated application
thread 'main' panicked at 'already borrowed: BorrowMutError', /home/popov/.cargo/registry/src/github.com-1ecc6299db9ec823/druid-shell-0.5.0/src/platform/gtk/window.rs:345:22
stack backtrace:
0: 0x558f6fa08355 - std::backtrace_rs::backtrace::libunwind::trace::h577ea05e9ca4629a
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/../../backtrace/src/backtrace/libunwind.rs:96
1: 0x558f6fa08355 - std::backtrace_rs::backtrace::trace_unsynchronized::h50b9b72b84c7dd56
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/../../backtrace/src/backtrace/mod.rs:66
2: 0x558f6fa08355 - std::sys_common::backtrace::_print_fmt::h6541cf9823837fac
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/sys_common/backtrace.rs:79
3: 0x558f6fa08355 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hf64fbff071026df5
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/sys_common/backtrace.rs:58
4: 0x558f6f9cfe9c - core::fmt::write::h9ddafa4860d8adff
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/core/src/fmt/mod.rs:1082
5: 0x558f6fa079b6 - std::io::Write::write_fmt::h1d2ee292d2b65481
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/io/mod.rs:1514
6: 0x558f6fa07340 - std::sys_common::backtrace::_print::ha25f9ff5080d886d
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/sys_common/backtrace.rs:61
7: 0x558f6fa07340 - std::sys_common::backtrace::print::h213e8aa8dc5405c0
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/sys_common/backtrace.rs:48
8: 0x558f6fa07340 - std::panicking::default_hook::{{closure}}::h6482fae49ef9d963
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/panicking.rs:200
9: 0x558f6fa06a53 - std::panicking::default_hook::he30ad7589e0970f9
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/panicking.rs:219
10: 0x558f6fa06a53 - std::panicking::rust_panic_with_hook::haa1ed36ada4ffb03
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/panicking.rs:569
11: 0x558f6fa066f8 - std::panicking::begin_panic_handler::{{closure}}::h7001af1bb21aeaeb
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/panicking.rs:476
12: 0x558f6fa066c4 - std::sys_common::backtrace::__rust_end_short_backtrace::h39910f557f5f2367
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/sys_common/backtrace.rs:153
13: 0x558f6fa0667d - rust_begin_unwind
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/std/src/panicking.rs:475
14: 0x558f6f9ce240 - core::panicking::panic_fmt::h4e2659771ebc78eb
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/core/src/panicking.rs:85
15: 0x558f6f9d1082 - core::option::expect_none_failed::h448b58a024c2c33a
at /rustc/18bf6b4f01a6feaf7259ba7cdae58031af1b7b39/library/core/src/option.rs:1221
16: 0x558f6f9e8253 - core::cell::RefCell<T>::borrow_mut::h3603befb390e1563
17: 0x558f6f9e97b1 - <O as gtk::auto::widget::WidgetExt>::connect_leave_notify_event::leave_notify_event_trampoline::h75875ed0bb521cbe
18: 0x7f6e198508f7 - <unknown>
19: 0x7f6e18a29346 - <unknown>
20: 0x7f6e18a443cd - g_signal_emit_valist
21: 0x7f6e18a4512f - g_signal_emit
22: 0x7f6e19998534 - <unknown>
23: 0x7f6e1999883d - <unknown>
24: 0x7f6e1999e707 - <unknown>
25: 0x7f6e1984da30 - <unknown>
26: 0x7f6e1984dd30 - <unknown>
27: 0x7f6e1973f3d0 - <unknown>
28: 0x7f6e1984dc01 - <unknown>
29: 0x7f6e199ad4c9 - <unknown>
30: 0x7f6e1984dc01 - <unknown>
31: 0x7f6e1984dea7 - <unknown>
32: 0x7f6e18a2910d - g_closure_invoke
33: 0x7f6e18a3c12e - <unknown>
34: 0x7f6e18a44715 - g_signal_emit_valist
35: 0x7f6e18a4512f - g_signal_emit
36: 0x7f6e199a10c6 - gtk_widget_show
37: 0x7f6e19879e20 - gtk_native_dialog_show
38: 0x7f6e1987a5fa - gtk_native_dialog_run
39: 0x558f6f9ebd6f - druid_shell::platform::gtk::window::WindowHandle::file_dialog::h61890d67b1dfd6d5
40: 0x558f6f9ba465 - druid::win_handler::AppState<T>::handle_cmd::hc2abc37aad9a458d
41: 0x558f6f9bab2f - druid::win_handler::AppState<T>::process_commands::h088db73c09277ecc
42: 0x558f6f9baa1e - druid::win_handler::AppState<T>::do_window_event::h72282a694bc2956c
43: 0x558f6f9c5125 - <druid::win_handler::DruidHandler<T> as druid_shell::window::WinHandler>::mouse_up::h6dea4b8b5390d8cc
44: 0x558f6f9e9a31 - <O as gtk::auto::widget::WidgetExt>::connect_button_release_event::button_release_event_trampoline::h50bb8aa8b40ec165
45: 0x7f6e198507fb - <unknown>
46: 0x7f6e18a2910d - g_closure_invoke
47: 0x7f6e18a3c05e - <unknown>
48: 0x7f6e18a440af - g_signal_emit_valist
49: 0x7f6e18a4512f - g_signal_emit
50: 0x7f6e19998534 - <unknown>
51: 0x7f6e1984d86e - <unknown>
52: 0x7f6e1984f948 - gtk_main_do_event
53: 0x7f6e19360765 - <unknown>
54: 0x7f6e19390f92 - <unknown>
55: 0x7f6e1874e417 - g_main_context_dispatch
56: 0x7f6e1874e650 - <unknown>
57: 0x7f6e1874e6dc - g_main_context_iteration
58: 0x7f6e18d0fefd - g_application_run
59: 0x558f6f9cb2d0 - kondo_ui::main::h725d4d5bbde190fc
60: 0x558f6f9b314c - std::sys_common::backtrace::__rust_begin_short_backtrace::h4fefc5af64538c72
61: 0x558f6f9cca0b - main
62: 0x7f6e17aefbf7 - __libc_start_main
63: 0x558f6f9ad3ea - _start
64: 0x0 - <unknown>
Hi!
At the moment kondo crashes if it hits something it can't open. Maybe show some warning that folder/file x
can not be analyzed and continue scanning.
I use version 0.2; build from git hash c2307fa.
$ kondo -V
kondo 0.2.0
$ RUST_BACKTRACE=1 kondo
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 13, kind: PermissionDenied, message: "Permission denied" }', src/libcore/result.rs:1188:5
stack backtrace:
0: backtrace::backtrace::libunwind::trace
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/libunwind.rs:88
1: backtrace::backtrace::trace_unsynchronized
at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.40/src/backtrace/mod.rs:66
2: std::sys_common::backtrace::_print_fmt
at src/libstd/sys_common/backtrace.rs:84
3: <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt
at src/libstd/sys_common/backtrace.rs:61
4: core::fmt::write
at src/libcore/fmt/mod.rs:1025
5: std::io::Write::write_fmt
at src/libstd/io/mod.rs:1426
6: std::sys_common::backtrace::_print
at src/libstd/sys_common/backtrace.rs:65
7: std::sys_common::backtrace::print
at src/libstd/sys_common/backtrace.rs:50
8: std::panicking::default_hook::{{closure}}
at src/libstd/panicking.rs:193
9: std::panicking::default_hook
at src/libstd/panicking.rs:210
10: std::panicking::rust_panic_with_hook
at src/libstd/panicking.rs:471
11: rust_begin_unwind
at src/libstd/panicking.rs:375
12: core::panicking::panic_fmt
at src/libcore/panicking.rs:84
13: core::result::unwrap_failed
at src/libcore/result.rs:1188
14: kondo::check_file_exists
15: <core::iter::adapters::FilterMap<I,F> as core::iter::traits::iterator::Iterator>::next
16: <core::iter::adapters::flatten::FlatMap<I,U,F> as core::iter::traits::iterator::Iterator>::next
17: kondo::main
18: std::rt::lang_start::{{closure}}
19: main
20: __libc_start_main
21: _start
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Currently kondo
hardcodes a list of possible CMake build directories. This often works well enough, but since the name of a CMake build directory is merely convention it can fail for directories with other names.
A more reliable way to discover CMake build directories would be to search for subdirectories with a generated file CMakeCache.txt
, but this cannot be supported in the current impl. Most of the infrastructure around artifact dirs assumes a static list of directories where instead a possible approach to address this would be to e.g., compute a (set of) globs for artifact_dirs
and then have consumers of that API dynamically check for glob matches in the file system (e.g., here). It might make sense to also centralize glob matching to reduce slow repeated and identical hits of the filesystem.
It seems that, currently, kondo
only deletes __pycache__
directories located in the root of a Python project, but this is not the only place they can occur (and often there isn't even one in the root). A __pycache__
directory can be created in any directory containing a .py
file, and .py
files can be organized in any arbitrary assortment of directories with any depth.
I'm not sure if this is the expected behavior but I came across this issue while I was working on #92
To reproduce:
$ cargo new repro
$ cargo build
# target directory is created
$ kondo
Projects cleaned: 0, Bytes deleted: 0.0B
# nothing is cleaned
I think this is due to:
Lines 57 to 61 in 51828a1
might be regression in #90
Here's some weird thing I do: I have a directory outside home where I put my target
, node_modules
etc, and I put symlinks on the project dirs. Those "shadow" directories are arranged in the same directory tree as the home directory. When I delete such build artifacts, I don't delete the directory that contains it (so I do not break the symlink). I do this to keep backups small.
I think your tool can help automate this workflow. I could pass a directory to it and it would move build dirs and set up symlinks. I may send a PR if you wish.
Anyway, thanks for this tool!
User Svenstaro on reddit mentioned StructOpt as a nice way to handle CLI arguments, especially as the supported options/flags grows.
To include recent changes, prompted by #64.
Kondo-ui doesn't seem to be published yet. At least cargo install kondo-ui
fails. I can't find a way starting kondo-ui
without downloading the binary directly or building it myself. Could you publish kondo-ui
to crates.io so installing via cargo is straight forward?
Could you edit your CI job to do something similar to this repo?
https://github.com/MyK00L/Tsuikaban-desktop/blob/master/.github/workflows/main.yml
so you can distribute a proper (even if unsigned) macOS app
๐ฅณ
(nice work @tbillington ; thanks for this)
Hey, thanks for this tool! ๐ป
I realized kondo
doesn't delete the Zig cache folder which is usually zig-cache
.
If appropriate, I would like to submit a PR for this!
Reddit user bcgroom mentioned a flag to output just a plain text line separated list of artifact directories. That way it could be passed/manipulated by other programs.
__pycache__
.mypy_cache
.nox
.pytest_cache
.ruff_cache
Add flag to only clean projects last mofied more than X days/weeks
Would deleting things that fall under explicit .gitignore
globs (as opposed to plain untracked files, which is wildly dangerous) be a useful thing for most people?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.